﻿using ET.TextHelper;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using System;
using System.Collections;
/*----------------------------------------------------------------
// Copyright (C) ET
// 版权所有。 
//
// 文件名：Plink

// 文件功能描述：MongoDB 操作

// 创建标识：胡进财 20140904
 
// 修改标识：

// 修改描述：

//----------------------------------------------------------------*/
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ET.Monitor.OperationDB
{
    public class MongoDB
    {
        string strPath = "", strName = "", strRealType = "";
        double val = 0;
        public MongoDB(string strInipath, string strIniName, string strIniRealType)
        {
            strPath = strInipath;
            strName = strIniName;
            strRealType = strIniRealType;
        }

        #region MongoDb 数据库连接 Mongos
        public MongoCollection<BsonDocument> CreateConn()
        {
            var conn = "mongodb://" + IniHelper.ReadIniData(strRealType, "DBIP", strPath, strName) + ":" + IniHelper.ReadIniData(strRealType, "DBPort", strPath, strName);//IP + 端口
            //var conn = "mongodb://192.168.12.206:21992";
            MongoClient client = new MongoClient(conn);

            MongoServer server = client.GetServer();
            MongoDatabase database = server.GetDatabase(IniHelper.ReadIniData(strRealType, "DBData", strPath, strName));//数据库名称 

            var collection = database.GetCollection(IniHelper.ReadIniData(strRealType, "DBName", strPath, strName));     //数据库表名称
            return collection;
        }

        public MongoCollection<TagModel> GetConn()
        {
            var conn = "mongodb://" + IniHelper.ReadIniData(strRealType, "DBIP", strPath, strName) + ":" + IniHelper.ReadIniData(strRealType, "DBPort", strPath, strName);//IP + 端口
            //var conn = "mongodb://192.168.12.206:21992";
            MongoClient client = new MongoClient(conn);

            MongoServer server = client.GetServer();
            MongoDatabase database = server.GetDatabase(IniHelper.ReadIniData(strRealType, "DBData", strPath, strName));//数据库名称 

            var collection = database.GetCollection<TagModel>(IniHelper.ReadIniData(strRealType, "DBName", strPath, strName));     //数据库表名称
            return collection;
        }
        #endregion

        #region 获取数据库连接 MongoDB  副本集
        public MongoCollection GetMongoconnection()
        {
            MongoClientSettings set = new MongoClientSettings();
            List<MongoServerAddress> servers = new List<MongoServerAddress>();
            servers.Add(new MongoServerAddress("192.168.20.206", 30001));
            servers.Add(new MongoServerAddress("192.168.20.207", 30001));
            servers.Add(new MongoServerAddress("192.168.20.208", 30001));
            set.Servers = servers;

            MongoClient client = new MongoClient(set);
            MongoServer server = client.GetServer();
            MongoDatabase database = server.GetDatabase("monitoring");
            MongoCollection collection = database.GetCollection("realtime");
            return collection;
        }
        #endregion

        /// <summary>
        /// 查询指定条件的所有数据
        /// </summary>
        /// <param name="qd"></param>
        /// <returns></returns>
        public IList<TagModel> GetVal(QueryDocument qd)
        {
            #region Mongos
            IList<TagModel> list = new List<TagModel>();

            list = CreateConn().FindAs<TagModel>(qd).ToList();

            return list;
            #endregion
        }

        /// <summary>
        /// 查询指定条件的第一条数据
        /// </summary>
        /// <param name="qd"></param>
        /// <returns>TagModel</returns>
        public TagModel GetOneVal(QueryDocument qd)
        {
            TagModel tVal = CreateConn().FindOneAs<TagModel>(qd);
            return tVal;
        }

        #region 获取实时数据
        /// <summary>
        /// 查询实时数据
        /// </summary>
        /// <param name="tagName"></param>
        /// <returns></returns>
        public object GetRealValue(string tagName)
        {
            double val = 0;
            var query = new QueryDocument { { "tag", tagName } };

            BsonDocument tag = GetMongoconnection().FindOneAs<BsonDocument>(query);

            SortByDocument sd = new SortByDocument();
            sd.Add("time", -1);
            MongoCursor<BsonDocument> mc = GetMongoconnection().FindAs<BsonDocument>(query).SetSortOrder(sd).SetLimit(1);
            if (mc.Count() > 0)
            {
                BsonDocument bd = mc.First();

                if (bd != null)

                    val = Convert.ToDouble(bd["value"]);

                return (object)val;

            }
            else
            {
                return null;
            }

        }
        #endregion

        /// <summary>
        /// 查询历史数据
        /// </summary>
        /// <param name="qd"></param>
        /// <returns></returns>
        public double GetHisValue(string tag, DateTime time)
        {
            #region Mongos
            //SortByDocument sd = new SortByDocument();
            //sd.Add("Time", -1);
            //MongoCursor<BsonDocument> mc = CreateConn().Find(qd).SetSortOrder(sd).SetLimit(1);
            //BsonDocument bd = mc.First();
            //var val = Convert.ToDouble(bd["Value"]);
            //return val;
            #endregion

            double val = 0;

            SortByDocument sd = new SortByDocument();
            sd.Add("time", -1);
            MongoCursor<BsonDocument> mc = GetMongoconnection().FindAs<BsonDocument>(Query.And(Query.EQ("tag", tag), Query.LTE("time", time))).SetSortOrder(sd).SetLimit(1);
            if (mc.Count() > 0)
            {
                BsonDocument bd = mc.First();
                if (bd != null)
                    val = Convert.ToDouble(bd["value"]);
            }
            return val;
        }

        public double[] GetHisVal(string tag, DateTime sTime, DateTime eTime)
        {
            double[] val = null;
            int count = 0;
            SortByDocument sd = new SortByDocument();
            sd.Add("time", 1);
            MongoCursor<BsonDocument> mc = GetMongoconnection().FindAs<BsonDocument>(Query.And(Query.EQ("tag", tag), Query.GTE("time", sTime), Query.LTE("time", eTime))).SetSortOrder(sd);
            val = new double[mc.Count()];
            foreach (var bd in mc)
            {
                if (val.Length > count)
                {
                    val[count] = Convert.ToDouble(bd["value"]);
                    count++;
                }
            }
            return val;
        }

        public DataTable GetHisValDt(string tag, DateTime sTime, DateTime eTime)
        {
            DataTable dt = new DataTable();
            SortByDocument sd = new SortByDocument();
            sd.Add("time", 1);
            MongoCursor<BsonDocument> mc = GetMongoconnection().FindAs<BsonDocument>(Query.And(Query.EQ("tag", tag), Query.GTE("time", sTime), Query.LTE("time", eTime))).SetSortOrder(sd);

            dt.Columns.Add("Tag", typeof(string));
            dt.Columns.Add("Time", typeof(DateTime));
            dt.Columns.Add("Value", typeof(double));
            //dt.Columns.Add("DescCN", typeof(string));
            //dt.Columns.Add("DescEN", typeof(string));
            //dt.Columns.Add("Zone", typeof(Int32));
            DataRow dr = dt.NewRow();
            long count = mc.Count();
            foreach (var bd in mc)
            {               
                dr["Tag"] = bd["tag"];
                dr["Time"] = bd["time"].ToString();
                dr["Value"] = Convert.ToDouble(bd["value"]);
                //dr["DescCN"] = bd["desccn"];
                //dr["DescEN"] = bd["descen"];
                //dr["Zone"] = Convert.ToInt32(bd["zone"].ToString());
                dt.Rows.Add(dr);
                dr = dt.NewRow();
            }
            int num = dt.Rows.Count;
            return dt;

        }


        public double[] GetHisVal(string tag, DateTime sTime, DateTime eTime, int second)
        {
            double[] val = null;
            int count = 0;
            string strVal = "";
            SortByDocument sd = new SortByDocument();
            sd.Add("time", -1);

            //sTime = sTime.AddHours(+8);
            //eTime = eTime.AddHours(+8);

            while (sTime < eTime)
            {
                MongoCursor<BsonDocument> mc = GetMongoconnection().FindAs<BsonDocument>(Query.And(Query.EQ("tag", tag), Query.LTE("time", sTime))).SetSortOrder(sd).SetLimit(1);

                if (mc.Count() > 0)
                {
                    BsonDocument bd = mc.First();

                    double v = 0;

                    strVal += bd["value"] + ",";
                }
                else
                    strVal += 0 + ",";

                sTime = sTime.AddSeconds(second);
                count++;
            }
            val = new double[count];
            for (int i = 0; i < count; i++)
            {
                val[i] = Convert.ToDouble(strVal.Split(',')[i]);
            }
            return val;
        }

        public IList<Hashtable> GetHisValue(string tag, DateTime sTime, DateTime eTime, int count)
        {
            IList<Hashtable> list = new List<Hashtable>();

            while (sTime < eTime)
            {
                SortByDocument sd = new SortByDocument();
                sd.Add("time", -1);

                MongoCursor<BsonDocument> mc = GetMongoconnection().FindAs<BsonDocument>(Query.And(Query.EQ("tag", tag), Query.GTE("time", eTime), Query.LT("time", sTime))).SetSortOrder(sd).SetLimit(1);

                BsonDocument bd = mc.First();
                if (bd != null)
                {
                    Hashtable ht = new Hashtable();
                    ht.Add("data", Convert.ToDouble(bd["value"]));
                    ht.Add("time", bd["time"]);
                    list.Add(ht);
                }
            }
            return list;
        }

        #region UTC
        //将一个事件对象转换为UTC格式的时间
        public static int DateTimeToUTC(DateTime DT)
        {
            long a = new DateTime(1970, 1, 1, 0, 0, 0, 0).Ticks;
            int rtnInt = 0;
            rtnInt = (int)((DT.Ticks - 8 * 3600 * 1e7 - a) / 1e7);
            return rtnInt;
        }
        #endregion


        /// <summary>
        /// 插入数据  批量  或   单条
        /// </summary>
        /// <param name="documents"></param>
        public void AddVal(List<BsonDocument> documents)
        {
            CreateConn().InsertBatch(documents);
        }

        public double GetConnection()
        {
            IList<MongoServerAddress> list = new List<MongoServerAddress>();

            MongoClientSettings set = new MongoClientSettings();
            List<MongoServerAddress> servers = new List<MongoServerAddress>();
            servers.Add(new MongoServerAddress("192.168.20.206", 30001));
            servers.Add(new MongoServerAddress("192.168.20.207", 30001));
            servers.Add(new MongoServerAddress("192.168.20.208", 30001));
            set.Servers = servers;

            MongoClient client = new MongoClient(set);
            MongoServer server = client.GetServer();
            MongoDatabase database = server.GetDatabase("monitoring");
            MongoCollection collection = database.GetCollection("realtime");

            var query = new QueryDocument { { "tag", "tag52341" } };

            BsonDocument tag = collection.FindOneAs<BsonDocument>(query);

            SortByDocument sd = new SortByDocument();
            sd.Add("DataTimes", -1);
            MongoCursor<BsonDocument> mc = collection.FindAs<BsonDocument>(query).SetSortOrder(sd).SetLimit(1);
            BsonDocument bd = mc.First();


            //Query.And(Query.EQ("name", "a"), Query.EQ("title", "t"));

            //foreach (BsonDocument bd in mc)
            //{
            //   double val = Convert.ToDouble(bd["value"]);
            //}



            return 0;
        }
    }
    public class TagModel
    {
        object _id;

        public object Id
        {
            get { return _id; }
            set { _id = value; }
        }
        string tag;

        public string Tag
        {
            get { return tag; }
            set { tag = value; }
        }
        double value;

        public double Value
        {
            get { return this.value; }
            set { this.value = value; }
        }
        DateTime time;

        public DateTime Time
        {
            get { return time; }
            set { time = value; }
        }
        string desc;

        public string Desc
        {
            get { return desc; }
            set { desc = value; }
        }
    }
}